package com.espirit.weixin.message;

import java.io.InputStream;
import java.io.Writer;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.googlecode.cswish.util.bean.ModelUtil;
import com.opensymphony.xwork2.ActionContext;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

public final class MessageUtil {

	private static final Log logger = LogFactory.getLog(MessageUtil.class);

	/**
	 * 返回消息类型：文本
	 */
	public static final String RESP_MESSAGE_TYPE_TEXT = "text";

	/**
	 * 返回消息类型：音乐
	 */
	public static final String RESP_MESSAGE_TYPE_MUSIC = "music";

	/**
	 * 返回消息类型：图文
	 */
	public static final String RESP_MESSAGE_TYPE_NEWS = "news";

	/**
	 * 请求消息类型：文本
	 */
	public static final String REQ_MESSAGE_TYPE_TEXT = "text";

	/**
	 * 请求消息类型：图片
	 */
	public static final String REQ_MESSAGE_TYPE_IMAGE = "image";

	/**
	 * 请求消息类型：链接
	 */
	public static final String REQ_MESSAGE_TYPE_LINK = "link";

	/**
	 * 请求消息类型：地理位置
	 */
	public static final String REQ_MESSAGE_TYPE_LOCATION = "location";

	/**
	 * 请求消息类型：音频
	 */
	public static final String REQ_MESSAGE_TYPE_VOICE = "voice";

	/**
	 * 请求消息类型：视频
	 */
	public static final String REQ_MESSAGE_TYPE_VIDEO = "video";

	/**
	 * 请求消息类型：推送
	 */
	public static final String REQ_MESSAGE_TYPE_EVENT = "event";

	/**
	 * 事件类型：subscribe(订阅)
	 */
	public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";

	/**
	 * 事件类型：unsubscribe(取消订阅)
	 */
	public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";

	/**
	 * 事件类型：用户已关注时的事件推送(扫描带参数二维码事件)
	 */
	public static final String EVENT_TYPE_SCAN = "SCAN";

	/**
	 * 事件类型：CLICK(自定义菜单点击事件)
	 */
	public static final String EVENT_TYPE_CLICK = "CLICK";
	
	/**
	 * 事件类型：LOCATION(上报地理位置事件), 注：有别于REQ_MESSAGE_TYPE_LOCATION
	 */
	public static final String EVENT_TYPE_LOCATION = "LOCATION";

	public static Map<String, String> parseXml(String xml) {
		// 将解析结果存储在HashMap中
		Map<String, String> map = new HashMap<String, String>();

		InputStream inputStream = null;

		try {
			inputStream = IOUtils.toInputStream(xml);

			SAXReader reader = new SAXReader();
			Document document = reader.read(inputStream);
			Element root = document.getRootElement();
			@SuppressWarnings("unchecked")
			List<Element> elementList = root.elements();

			for (Element e : elementList) {
				map.put(StringUtils.uncapitalize(e.getName()), e.getText());
			}
		} catch (DocumentException e) {
			logger.error("parse message xml failed.", e);
		} finally {
			IOUtils.closeQuietly(inputStream);
		}

		return map;
	}

	public static <T extends BaseMessage> T newMessage(Class<T> clazz) {
		T message = ModelUtil.newInstance(clazz);
		Map<String, Object> parameters = ActionContext.getContext().getParameters();
		message.setCreateTime(Calendar.getInstance().getTime().getTime());
		String[] fromUserName = (String[]) parameters.get("fromUserName");
		String[] toUserName = (String[]) parameters.get("toUserName");
		String[] msgType = (String[]) parameters.get("msgType");
		message.setFromUserName(fromUserName[0]);
		message.setToUserName(toUserName[0]);
		message.setMsgType(msgType[0]);
		String simpleName = clazz.getSimpleName();
		if (simpleName.endsWith("Message")) {
			message.setMsgType(simpleName.substring(0, simpleName.length() - 7).toLowerCase());
		}
		return message;
	}
	
	public static String textMessageToXml(TextMessage textMessage) {
		xstream.alias("xml", TextMessage.class);
		return xstream.toXML(textMessage);
	}

	public static String musicMessageToXml(MusicMessage musicMessage) {
		xstream.alias("xml", MusicMessage.class);
		return xstream.toXML(musicMessage);
	}

	public static String articleMessageToXml(ArticleMessage articleMessage) {
		xstream.alias("xml", ArticleMessage.class);
		xstream.alias("item", new Article().getClass());
		return xstream.toXML(articleMessage);
	}

	private static XStream xstream = new XStream(new XppDriver() {
		public HierarchicalStreamWriter createWriter(Writer out) {
			return new PrettyPrintWriter(out) {
				// 对所有xml节点的转换都增加CDATA标记
				boolean cdata = true;

				public void startNode(String name, @SuppressWarnings("rawtypes") Class clazz) {
					String upcaseName = name;
					if (!("xml".equals(name) || "item".equals(name))) {
						upcaseName = StringUtils.capitalize(name);
					}
					super.startNode(upcaseName, clazz);
				}

				protected void writeText(QuickWriter writer, String text) {
					if (cdata) {
						writer.write("<![CDATA[");
						writer.write(text);
						writer.write("]]>");
					} else {
						writer.write(text);
					}
				}
			};
		}
	});

	public static String getMessageClassName(String type) {
		String className = null;

		if (REQ_MESSAGE_TYPE_TEXT.equals(type)) {
			className = TextMessage.class.getName();
		} else if (REQ_MESSAGE_TYPE_IMAGE.equals(type)) {
			className = ImageMessage.class.getName();
		} else if (REQ_MESSAGE_TYPE_LINK.equals(type)) {
			className = LinkMessage.class.getName();
		} else if (REQ_MESSAGE_TYPE_LOCATION.equals(type)) {
			className = LocationMessage.class.getName();
		} else if (REQ_MESSAGE_TYPE_VOICE.equals(type)) {
			className = VoiceMessage.class.getName();
		} else if (REQ_MESSAGE_TYPE_VIDEO.equals(type)) {
			className = VideoMessage.class.getName();
		} else if (REQ_MESSAGE_TYPE_EVENT.equals(type)) {
			className = EventMessage.class.getName();
		}

		return className;
	}

}
